home *** CD-ROM | disk | FTP | other *** search
- /* Copyright 2008, Boomtango.com. All Rights Reserved. */
- /* storage.js
- * Responsible for data storage
- */
-
- var EXPORTED_SYMBOLS = ["boomtangoStorage"];
-
- var boomtangoStorage = {
- DBVERSION: 1,
-
- /*
- Returns a SQL conditional fragment based on starttime, endtime, types. Output is expected to be
- sanitized. Assumes 'types' is trusted and ensures starttime/endtime is an integer.
- */
- _buildWhereClause: function(starttime, endtime, types, skipTimes, dedupe){
- var r = [];
- var start = parseInt(starttime);
- var end = parseInt(endtime);
-
- if(!skipTimes){
- r.push( "(starttime>= ", start, " AND starttime<= ", end, ")");
- }
- if(types){
- r.push(r.length ? " AND (" : " (");
-
- var len = types.length;
- for(var x = 0; x < len; ){
- r.push("type = '", types[x], "'");
- x++;
- if(x < len){
- r.push(" OR ");
- }
- }
- r.push(")");
- }
-
- if(dedupe){
- var where;
- r.push(r.length ? " AND (" : " (");
- r.push("ftsrowid not in (SELECT ftsrowid FROM tracker WHERE ");
- where = this._buildWhereClause(start, end, null, skipTimes, false);
- if (where) {
- r.push(where + " AND ");
- }
- r.push("type != 'web')");
-
- r.push(")");
- }
-
- return r.join("");
- },
- deleteAllThumb: function() {
- this.app.log("storage::deleteAllThumb: ");
- var sql = "DELETE FROM thumb;VACUUM;";
- this.conn.executeSimpleSQL(sql);
- },
- updateThumb: function(id, data){
- var now = Date.now();
- var sql = ["UPDATE thumb SET data = ",
- "'", data, "' , createtime = ", now, " WHERE ",
- "id = ",id,
- ].join("");
- this.conn.executeSimpleSQL(sql);
-
- },
- getThumbID: function(url){
- var res = -1;
- var sql = ["SELECT ",
- "id,",
- " createtime",
- " FROM thumb WHERE url = ?1"
- ].join("");
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, url);
-
- if (statement.executeStep()) {
- res = {
- id: statement.getInt64(0),
- createtime: statement.getInt64(1)
- };
- }
-
- if(res.id === undefined){
- res = { id: -1 };
- }
- statement.reset();
-
- return res;
- },
- getBlacklist: function(allrecs){
- this.app.log("storage::getBlacklist");
- var sql = ["SELECT ",
- "data",
- " FROM blacklist",
- (allrecs ? "" : " WHERE internalOnly = 0")
- ].join("");
- var statement = this.conn.createStatement(sql);
-
- var res = [];
- while (statement.executeStep()) {
- res.push(statement.getString(0));
- }
-
- this.app.debug("Num Results: " + res.length);
- statement.reset();
-
- return res;
- },
- addBlacklistData: function(data, internalOnly){
- this.app.log("storage::addBlacklistData (" + data + ")");
- var sql = ["INSERT INTO blacklist (",
- "data, ",
- "internalOnly",
- ") VALUES (",
- "?1, ",
- "?2 ",
- ")"
- ].join('');
-
- var statement = this.conn.createStatement(sql);
- statement.bindUTF8StringParameter(0, data);
- statement.bindInt64Parameter(1, internalOnly);
- statement.execute();
- statement.reset();
- this.app.log("storage::addBlacklistData result = " + this.conn.lastInsertRowID + ")");
- return this.conn.lastInsertRowID;
- },
- deleteBlacklistData: function(data){
- var sql = "DELETE FROM blacklist WHERE data = ?1";
- var statement = this.conn.createStatement(sql);
- statement.bindUTF8StringParameter(0, data);
- statement.execute();
- statement.reset();
- this.app.log("deleteBlacklistData: " + data);
- },
- // XXX: THIS DELETS ALL BLACKLIST URLS. ONLY USED WHEN USER SPECIFIES INTENT
- deleteAllBlacklist: function(){
- this.app.log("storage::deleteAllBlacklist");
- var sql = "DELETE FROM blacklist WHERE internalOnly = 0";
- this.conn.executeSimpleSQL(sql);
- },
- addThumb: function(url, thumb){
- this.app.log("storage::addThumb (" + url + ")");
- var now = Date.now();
- var sql = ["INSERT INTO thumb (",
- "url,",
- "createtime,",
- "data",
- ") VALUES (",
- "?1, ",
- "?2, ",
- "?3 ",
- ")"
- ].join('');
-
- var statement = this.conn.createStatement(sql);
- statement.bindUTF8StringParameter(0, url);
- statement.bindInt64Parameter(1, now);
- statement.bindUTF8StringParameter(2, thumb);
- statement.execute();
- statement.reset();
- return this.conn.lastInsertRowID;
- },
- getThumb: function(id){
- var res = "";
- var is_id = typeof id == "number";
- var sql = ["SELECT ",
- "data",
- " FROM thumb WHERE",
- (is_id? " id = ?1" : " url = ?1")
- ].join("");
-
- var statement = this.conn.createStatement(sql);
-
- if (is_id) {
- statement.bindInt64Parameter(0, id);
- }
- else {
- statement.bindUTF8StringParameter(0, id);
- }
-
- if (statement.executeStep()) {
- res = statement.getString(0);
- }
-
- statement.reset();
-
- return res;
- },
-
- querySummary: function(starttime, endtime){
- var res = {};
-
- this.app.log("storage::querySummary");
-
- // get sums by type
- var sql = ["SELECT ",
- "sum(endtime - starttime), ",
- "count(*), ",
- "type FROM tracker WHERE ",
- this._buildWhereClause(starttime, endtime),
- " AND (endtime > 0)",
- " GROUP BY type"].join("");
-
- var statement = this.conn.createStatement(sql);
-
- res.types = [];
- while (statement.executeStep()) {
- res.types.push(
- {
- type: statement.getString(2),
- timespent: statement.getInt64(0),
- count: statement.getInt64(1)
- }
- );
- }
- statement.reset();
-
- var types = res.types;
- var len = types.length;
- res.urls = {};
- for(var x = 0; x < len; x++){
- var type = types[x].type;
- res.urls[type] = [];
-
- var sql = ["SELECT ",
- "sum(endtime - starttime), ",
- "type, ",
- "title, ",
- "ftsrowid, ",
- "id, ",
- "url FROM tracker WHERE ",
- this._buildWhereClause(starttime, endtime,[type]),
- " AND (endtime > 0)",
- " GROUP BY url ORDER BY sum(endtime - starttime) DESC LIMIT 5"].join("");
-
- var statement = this.conn.createStatement(sql);
-
- var a = res.urls[type];
- while (statement.executeStep()) {
- a.push(
- {
- url: statement.getString(5),
- type: statement.getString(1),
- title: statement.getString(2),
- ftsrowid: statement.getInt64(3),
- id: statement.getInt64(4),
- timespent: statement.getInt64(0),
- }
- );
- }
- statement.reset();
- }
-
- return res;
- },
- queryTrackerByTrackerID: function(id){
- var res = [];
- this.app.log("storage::queryTrackerByTrackerID");
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE id = ?1"
- ].join("");
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
-
-
- if (statement.executeStep()) {
- res.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- endtime: statement.getInt64(4),
- starttime: statement.getInt64(3),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- } else {
- return [];
- }
-
- statement.reset();
-
- // also grab the web version
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ftsrowid = ?1",
- " AND type = 'web'"
- ].join("");
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, res[0].ftsrowid);
-
- while (statement.executeStep()) {
- res.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- endtime: statement.getInt64(4),
- starttime: statement.getInt64(3),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
- return res;
- },
- queryTrackerByFTSRowId: function(id){
- var res = [];
- this.app.log("storage::queryTrackerByFTSRowId");
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ftsrowid = ?1"
- ].join("");
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
-
- while (statement.executeStep()) {
- res.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- endtime: statement.getInt64(4),
- starttime: statement.getInt64(3),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
-
- statement.reset();
-
- return res;
- },
- _queryTrackerBuildQuery: function(starttime, endtime, types, query, dedupe, getcount){
- var selectfields;
- if(getcount){
- selectfields = "count(*)";
-
- } else {
- selectfields = [
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview"].join('');
-
- }
- if(query){
- return ["SELECT ",
- selectfields,
- " FROM tracker WHERE ftsrowid IN (",
- "SELECT id FROM historyfts WHERE (starttime>=",
- starttime, " AND starttime <=", endtime,
- ") AND historyfts MATCH :query) AND ",
- this._buildWhereClause(starttime, endtime, types, true, dedupe)].join("");
- }
-
- return ["SELECT ",
- selectfields,
- " FROM tracker WHERE ",
- this._buildWhereClause(starttime, endtime, types, false, dedupe)].join("");
- },
- FTSIDToURL: function(id){
- var sql = "SELECT url FROM tracker WHERE ftsrowid = ?1 LIMIT 1";
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
-
- if (statement.executeStep()) {
- return statement.getString(0);
- }
- return "";
- },
- IDToURL: function(id){
- var sql = "SELECT url FROM tracker WHERE id = ?1";
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
-
- if (statement.executeStep()) {
- return statement.getString(0);
- }
- return "";
- },
- IDToTitle: function(id){
- var sql = "SELECT title FROM tracker WHERE id = ?1";
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
-
- if (statement.executeStep()) {
- return statement.getString(0);
- }
- return " ";
- },
- queryTrackerByID: function(id, order, offset, max, getcount, desc, types, starttime, endtime){
- this.app.log("storage::queryTrackerByID");
-
- var whereclause = "";
- if(starttime > 0){
- whereclause += " AND (starttime >= " + parseInt(starttime) + ")";
- }
- if(endtime > 0){
- whereclause += " AND (starttime <= " + parseInt(endtime) + ")";
- }
-
- var r = [];
- r.push(" AND (");
-
- var len = types.length;
- for(var x = 0; x < len; ){
- r.push("type = '", types[x], "'");
- x++;
- if(x < len){
- r.push(" OR ");
- }
- }
- r.push(")");
- var typeclause = r.join("");
- var res = { totalcount: 0, data: [] };
- var url = this.IDToURL(id);
- if(!url.length){
- return res;
- }
-
- // first get the count
- if(getcount){
- var sql = ["SELECT count(*) FROM tracker WHERE ",
- "url = ?1", whereclause, typeclause].join("");
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, url);
-
- if (statement.executeStep()) {
- res.totalcount = statement.getInt64(0);
- }
-
- statement.reset();
-
- this.app.debug("Total: " + res.totalcount);
- }
-
- // clean order
- switch(order){
- case 'timespent':
- order = '(endtime - starttime)';
- break;
- case 'title':
- case 'url':
- case 'starttime':
- case 'type':
- break;
- default:
- order = 'starttime';
- break;
- }
-
- // now get the data
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ",
- "url = ?1",whereclause, typeclause,
- " ORDER BY ", order, (desc ? " DESC" : ""),
- " LIMIT ", max,
- " OFFSET ", offset].join("");
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, url);
-
- while (statement.executeStep()) {
- res.data.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.data.length);
- statement.reset();
-
- return res;
- },
- queryTrackerByMoreItems: function(type, starttime, endtime, order, offset, max, getcount, desc){
- var res = { totalcount: 0, data: [] };
- this.app.log("storage::queryTrackerByMoreItems");
-
- // first get the count
- if(getcount){
- var sql = ["SELECT id FROM tracker WHERE ",
- this._buildWhereClause(starttime, endtime, [type], false, false),
- " GROUP BY url, preview"
- ].join("");
- var sql2 = ["SELECT COUNT(*) FROM (",
- sql,
- ")"
- ].join("");
- var statement = this.conn.createStatement(sql2);
-
- if (statement.executeStep()) {
- res.totalcount = statement.getInt64(0);
- }
-
- statement.reset();
-
- this.app.debug("Total: " + res.totalcount);
- }
-
- // clean order
- switch(order){
- case 'timespent':
- order = '(endtime - starttime)';
- break;
- case 'title':
- case 'url':
- case 'starttime':
- case 'type':
- break;
- default:
- order = 'starttime';
- break;
- }
-
- // now get the data
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ",
- this._buildWhereClause(starttime, endtime, [type], false, false),
- " GROUP BY url, preview",
- " ORDER BY ", order, (desc ? " DESC" : ""),
- " LIMIT ", max,
- " OFFSET ", offset].join("");
- var statement = this.conn.createStatement(sql);
- while (statement.executeStep()) {
- res.data.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.data.length);
- statement.reset();
-
- return res;
- },
- _cleanQuery: function(query){
- // sqlite crashes when there is a + or - in a match
- return query.replace(/[+-]/g,' ');
- },
- queryTrackerBySERP: function(query){
- var res = { totalcount: 0, data: [] };
- this.app.log("storage::queryTrackerBySERP");
- query = this._cleanQuery(query);
-
- // first get the count
- var sql = "SELECT count(DISTINCT url) FROM historyfts WHERE historyfts MATCH ?1 AND url NOT LIKE '%google.%'";
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, query);
-
- if (statement.executeStep()) {
- res.totalcount = statement.getInt64(0);
- }
-
- statement.reset();
-
- this.app.debug("Total: " + res.totalcount);
-
- // now get the data
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ",
- "ftsrowid IN (",
- "SELECT id FROM historyfts WHERE historyfts MATCH ?1 AND url NOT LIKE '%google.%')",
- "GROUP BY url",
- " ORDER BY starttime DESC",
- " LIMIT 3",
- " OFFSET 0"].join("");
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, query);
-
- while (statement.executeStep()) {
- res.data.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.data.length);
- statement.reset();
-
- return res;
- },
- queryTrackerBySearch: function(query, order, offset, max, getcount, desc, types, starttime, endtime){
- var res = { totalcount: 0, data: [] };
- this.app.log("storage::queryTrackerBySearch");
-
- query = this._cleanQuery(query);
- var whereclause = "";
- if(starttime > 0){
- whereclause += " AND (starttime >= " + starttime + ")";
- }
- if(endtime > 0){
- whereclause += " AND (starttime <= " + endtime + ")";
- }
-
- var r = [];
- r.push(" AND (");
-
- var len = types.length;
- for(var x = 0; x < len; ){
- r.push("type = '", types[x], "'");
- x++;
- if(x < len){
- r.push(" OR ");
- }
- }
- r.push(")");
- var typeclause = r.join("");
- // first get the count
- if(getcount){
- var sql = ["SELECT count(DISTINCT title)",
- " FROM tracker WHERE ",
- "ftsrowid IN (",
- "SELECT id FROM historyfts WHERE historyfts MATCH ?1)",
- whereclause, typeclause].join("");
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, query);
-
- if (statement.executeStep()) {
- res.totalcount = statement.getInt64(0);
- }
-
- statement.reset();
-
- this.app.debug("Total: " + res.totalcount);
- }
-
- // clean order
- switch(order){
- case 'timespent':
- order = '(endtime - starttime)';
- break;
- case 'title':
- case 'url':
- case 'starttime':
- case 'type':
- break;
- default:
- order = 'starttime';
- break;
- }
-
- // now get the data
- var sql = ["SELECT ",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "id,",
- "preview FROM tracker WHERE ",
- "ftsrowid IN (",
- "SELECT id FROM historyfts WHERE historyfts MATCH ?1)",
- whereclause, typeclause,
- " GROUP BY title ",
- " ORDER BY ", order, (desc ? " DESC" : ""),
- " LIMIT ?3",
- " OFFSET ?4"].join("");
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindUTF8StringParameter(0, query);
- statement.bindUTF8StringParameter(1, order);
- statement.bindInt64Parameter(2, max);
- statement.bindInt64Parameter(3, offset);
-
- while (statement.executeStep()) {
- res.data.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- id: statement.getInt64(6),
- preview: statement.getString(7)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.data.length);
- statement.reset();
-
- return res;
- },
- queryTrackerByCategory: function(starttime, endtime, types, query, max, dedupe){
- var res = {};
- this.app.log("storage::queryTrackerByCategory: " + query);
- var len = types.length;
- for(var x = 0; x < len; x++){
- var type = types[x];
-
- // builds a sql statement with :query as a bind parameter
- var sql = this._queryTrackerBuildQuery(starttime, endtime, [type], query, dedupe);
-
- sql += "GROUP BY url, preview ORDER BY id DESC";
- if(max){
- sql += " LIMIT " + max;
- }
-
- var statement = this.conn.createStatement(sql);
-
- if (query) {
- var queryidx = statement.getParameterIndex(":query");
- statement.bindUTF8StringParameter(queryidx, query);
- }
-
- while (statement.executeStep()) {
- var url = statement.getString(0);
-
- if(!res.hasOwnProperty(type)){
- res[type] = [];
- }
-
- res[type].push(
- {
- url: url,
- title: statement.getString(1),
- type: type,
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- preview: statement.getString(7),
- id: statement.getInt64(6)
- }
- );
- }
-
- statement.reset();
- }
-
- return res;
- },
- queryTrackerByThumbnail: function(starttime, endtime, types, query, offset, max){
- var res = [];
- var total = 0;
- this.app.log("storage::queryTracker: " + query);
-
- // first get count
- var sql = this._queryTrackerBuildQuery(starttime, endtime, types, query, false, true);
- var statement = this.conn.createStatement(sql);
-
- if (query) {
- var queryidx = statement.getParameterIndex(":query");
- statement.bindUTF8StringParameter(queryidx, query);
- }
-
- if(statement.executeStep()){
- total = statement.getInt64(0);
- }
- statement.reset();
-
- // next get our data
- var sql = this._queryTrackerBuildQuery(starttime, endtime, types, query) +
- "ORDER BY starttime DESC LIMIT " + max + " OFFSET " + offset;
- var statement = this.conn.createStatement(sql);
-
- if (query) {
- var queryidx = statement.getParameterIndex(":query");
- statement.bindUTF8StringParameter(queryidx, query);
- }
- while (statement.executeStep()) {
- res.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- preview: statement.getString(7),
- id: statement.getInt64(6)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.length);
- statement.reset();
-
- return { total: total, data: res };
- },
- queryTracker: function(starttime, endtime, types, query){
- var res = [];
- this.app.log("storage::queryTracker: " + query);
-
- // builds a sql statement with :query as a bind parameter
- var sql = this._queryTrackerBuildQuery(starttime, endtime, types, query);
-
- var statement = this.conn.createStatement(sql);
-
- if (query) {
- var queryidx = statement.getParameterIndex(":query");
- statement.bindUTF8StringParameter(queryidx, query);
- }
-
- while (statement.executeStep()) {
- res.push(
- {
- url: statement.getString(0),
- title: statement.getString(1),
- type: statement.getString(2),
- starttime: statement.getInt64(3),
- endtime: statement.getInt64(4),
- ftsrowid: statement.getInt64(5),
- preview: statement.getString(7),
- id: statement.getInt64(6)
- }
- );
- }
-
- this.app.debug("Num Results: " + res.length);
- statement.reset();
-
- return res;
- },
- resetDB: function(){
- this.app.debug("storage::resetDB");
- // for now, delete any old dbs
- var file = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- file.append("boomtango.sqlite");
- try {
- file.remove(false);
- } catch(e){}
- },
- upgradeDB: function(){
- this.app.debug("storage::upgradeDB to " + this.DBVERSION);
- // for now, delete any old dbs
- var file = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- file.append("boomtango.sqlite");
- try {
- file.remove(false);
- } catch(e){}
- this.app.dbversion = this.DBVERSION;
- },
- _fileCopy: function(fromFile, toFile) {
- try {
- // READ file (binary)
- var istream = Components.classes["@mozilla.org/network/file-input-stream;1"].
- createInstance(Components.interfaces.nsIFileInputStream);
- istream.init(fromFile, -1, -1, false);
-
- var bstream = Components.classes["@mozilla.org/binaryinputstream;1"].
- createInstance(Components.interfaces.nsIBinaryInputStream);
- bstream.setInputStream(istream);
-
- var bytes = bstream.readBytes(bstream.available());
- this.app.log("READ FILE LENGTH: " + bytes.length);
-
- // WRITE file (binary)
- var ostream = Components.classes["@mozilla.org/network/safe-file-output-stream;1"].
- createInstance(Components.interfaces.nsIFileOutputStream);
- ostream.init(toFile, 0x04 | 0x08 | 0x20, 0600, 0); // write, create, truncate
-
- ostream.write(bytes, bytes.length);
- if (ostream instanceof Components.interfaces.nsISafeOutputStream) {
- ostream.finish();
- } else {
- ostream.close();
- }
- }
- catch (err) {
- this.app.log("ERROR: " + err);
- return false;
- }
- return true;
- },
- backupToFile: function(filename){
- var backupfile = Components.classes["@mozilla.org/file/local;1"].
- createInstance(Components.interfaces.nsILocalFile);
- backupfile.initWithPath(filename);
-
- var dbfile = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- dbfile.append("boomtango");
- dbfile.append("data");
- dbfile.append("boomtango.sqlite");
-
- return this._fileCopy(dbfile, backupfile);
- },
- validBackup: function(file){
- try {
- // check if we can open db
- var storageService = Components.classes["@mozilla.org/storage/service;1"]
- .getService(Components.interfaces.mozIStorageService);
- var backupconn = storageService.openUnsharedDatabase(file);
-
- var sql = "select name from SQLite_Master";
- var statement = backupconn.createStatement(sql);
-
- var res = [];
- while (statement.executeStep()) {
- // create a hash
- res[statement.getString(0)] = true;
- this.app.log("VALIDATE:" + statement.getString(0));
- }
-
- // verify existance of required tables
- var required_tables = ["tracker",
- "thumb",
- "blacklist"];
-
-
- this.app.debug("Num Results: " + res.length);
-
- for (x in required_tables) {
- if (!res[required_tables[x]]) {
- this.app.log('cant find ' + required_tables[x]);
- return false;
- }
- }
- statement.reset();
- }
- catch (ex) {
- return false;
- }
-
- return true;
- },
- restoreFromFile: function(filename){
- var backupfile = Components.classes["@mozilla.org/file/local;1"].
- createInstance(Components.interfaces.nsILocalFile);
- backupfile.initWithPath(filename);
-
- var dbfile = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- dbfile.append("boomtango");
- dbfile.append("data");
- dbfile.append("boomtango.sqlite");
-
- if (!this.validBackup(backupfile)) {
- return false;
- }
-
- this._fileCopy(backupfile, dbfile);
-
- // re-initialize
-
- var file = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- file.append("boomtango");
- file.append("data");
- file.append("boomtango.sqlite");
-
- this.app.log("dbversion=" + this.DBVERSION);
- this.app.log("current version=" + this.app.dbversion);
-
- if(this.app.dbversion < this.DBVERSION){
- this.upgradeDB();
- }
- var storageService = Components.classes["@mozilla.org/storage/service;1"]
- .getService(Components.interfaces.mozIStorageService);
-
- this.conn = storageService.openUnsharedDatabase(file);
- this.app.debug("storage::re-init");
- this.app.reloadTabsWithAttribute("boomtangoHistory");
-
- return true;
- },
- init: function(app){
- this.app = app;
- var file = Components.classes["@mozilla.org/file/directory_service;1"]
- .getService(Components.interfaces.nsIProperties)
- .get("ProfD", Components.interfaces.nsIFile);
- file.append("boomtango");
- file.append("data");
- file.append("boomtango.sqlite");
-
- this.app.log("dbversion=" + this.DBVERSION);
- this.app.log("current version=" + this.app.dbversion);
-
- if(this.app.killBTData){
- this.app.killBTData = false;
- this.resetDB();
- } else if(this.app.dbversion < this.DBVERSION){
- this.upgradeDB();
- }
- var storageService = Components.classes["@mozilla.org/storage/service;1"]
- .getService(Components.interfaces.mozIStorageService);
- var newdb = !file.exists();
- this.conn = storageService.openUnsharedDatabase(file);
- this.app.debug("storage::init");
-
- if(newdb){
- this.initTables();
- this.loadFromHistory();
- }
- this.init = function(){};
- },
- loadFromHistory: function(){
- this.app.debug("storage::loadFromHistory");
- this.app.newUser = true;
- },
- cleanupDB: function(){
- var lastcleanup = this.app.lastcleanup;
- var lastshutdown = this.app.lastshutdown;
- var self = this;
-
- // write our current time each minute in case of crash
- var callback = {
- notify: function(){
- var d = new Date();
- self.app.lastshutdown = d.getTime();
- }
- };
- var timer = Components.classes["@mozilla.org/timer;1"]
- .createInstance(Components.interfaces.nsITimer);
- timer.initWithCallback(callback, 60*1000, Components.interfaces.nsITimer.TYPE_REPEATING_SLACK);
- callback.notify();
-
- var query = ["UPDATE tracker SET endtime=",
- lastshutdown, " WHERE ",
- "starttime > ", lastcleanup, " AND endtime < 0"
- ].join('');
- this.conn.executeSimpleSQL(query);
-
- var now = new Date();
- this.app.lastcleanup = now.getTime();
- },
- initTables: function() {
- this.app.debug("storage::inittables");
- this.conn.executeSimpleSQL("create virtual table historyfts using fts3(title TEXT,content TEXT, url TEXT, starttime INTEGER, endtime INTEGER, id INTEGER);");
-
- // Setup thumb table
- this.conn.executeSimpleSQL(["CREATE TABLE IF NOT EXISTS thumb (",
- "id INTEGER PRIMARY KEY,",
- "url TEXT,",
- "createtime INTEGER,",
- "data TEXT)"
- ].join(''));
- this.conn.executeSimpleSQL(["CREATE INDEX IF NOT EXISTS thumb_url_index ",
- "ON thumb (url)"
- ].join(''));
- // Setup blacklist table
- this.conn.executeSimpleSQL(["CREATE TABLE IF NOT EXISTS blacklist (",
- "id INTEGER PRIMARY KEY,",
- "internalOnly INTEGER,",
- "data TEXT)"
- ].join(''));
-
- this.addBlacklistData("chrome://*", 1);
- this.addBlacklistData("about:*", 1);
- // Setup tracker table
- this.conn.executeSimpleSQL(["CREATE TABLE IF NOT EXISTS tracker (",
- "id INTEGER PRIMARY KEY,",
- "url TEXT,",
- "title TEXT,",
- "type TEXT,",
- "ftsrowid INTEGER,",
- "starttime INTEGER,",
- "endtime INTEGER,",
- "preview TEXT)"
- ].join(''));
- this.conn.executeSimpleSQL(["CREATE INDEX IF NOT EXISTS ftsrowid_index ",
- "ON tracker (ftsrowid)"
- ].join(''));
- this.conn.executeSimpleSQL(["CREATE INDEX IF NOT EXISTS starttime_index ",
- "ON tracker (starttime)"
- ].join(''));
- },
- addFTS: function(title, content, starttime, endtime, url){
- this.app.log("storage::addFTS: " + title);
- this.app.log("(" + url + ")");
- var sql = ["INSERT INTO historyfts (",
- "title,",
- "content, url, starttime, endtime, id) VALUES (",
- "?1, ",
- "?2, ?3, ?4, ?5, ?6)"
- ].join('');
- var statement = this.conn.createStatement(sql);
- var result = this.app.getNextID();
- statement.bindUTF8StringParameter(0, title);
- statement.bindUTF8StringParameter(1, content);
- statement.bindUTF8StringParameter(2, url);
- statement.bindInt64Parameter(3, starttime);
- statement.bindInt64Parameter(4, endtime);
- statement.bindInt64Parameter(5, result);
- statement.execute();
- statement.reset();
-
- return result;
- },
- /* Tracker Commands */
- addTrackers: function(url, title, ftsrowid, starttime, endtime, trackers){
- this.app.log("storage::addTrackers: " + title + " (" + trackers.length + ")");
- if(trackers){
- var len = trackers.length;
- while(len--){
- var trackertitle = trackers[len].title || title;
- this._addTracker(url, trackertitle, ftsrowid, starttime, endtime, trackers[len]);
- }
- }
- },
- _addTracker: function(url, title, ftsrowid, starttime, endtime, tracker) {
- var sql = ["INSERT INTO tracker (",
- "url,",
- "title,",
- "type,",
- "starttime,",
- "endtime,",
- "ftsrowid,",
- "preview) VALUES (",
- "?1, ",
- "?2, ",
- "?3, ",
- "?4, ",
- "?5, ",
- "?6, ",
- "?7)"
- ].join('');
-
- var statement = this.conn.createStatement(sql);
- statement.bindUTF8StringParameter(0, url);
- statement.bindUTF8StringParameter(1, title);
- statement.bindUTF8StringParameter(2, tracker.type);
- statement.bindInt64Parameter(3, starttime);
- statement.bindInt64Parameter(4, endtime);
- statement.bindUTF8StringParameter(5, ftsrowid);
- statement.bindUTF8StringParameter(6, tracker.preview);
- statement.execute();
- statement.reset();
-
- return this.conn.lastInsertRowID;
- },
- // XXX: THIS DELETS ALL TRACKERS. ONLY USED WHEN USER SPECIFIES INTENT
- deleteAllTrackers: function(){
- this.app.log("storage::deleteAllTrackers");
- var sql = "DELETE FROM tracker";
- this.conn.executeSimpleSQL(sql);
- },
- deleteTrackersForFTSRowId: function(id){
- this.app.log("storage::deleteTrackersForFTSRowId: " + id);
- var sql = "DELETE FROM tracker WHERE ftsrowid = ?1";
-
- var statement = this.conn.createStatement(sql);
-
- statement.bindInt64Parameter(0, id);
- statement.executeStep();
- statement.reset();
- },
- deleteTrackersForURL: function(url){
- this.app.log("storage::deleteTrackersForURL: " + url);
- var sql = ["DELETE FROM tracker WHERE url = '",
- url, "'"].join("");
- this.conn.executeSimpleSQL(sql);
- },
- updateTrackerEnd: function(url, end, ftsrowid){
- var sql = ["UPDATE tracker SET endtime = ", end, " WHERE url = '",
- url, "'", " AND endtime < 0"].join("");
- this.conn.executeSimpleSQL(sql);
-
- }
- };
-